package cRpc

import (
	"errors"
	"fmt"
	"reflect"

	"github.com/gin-gonic/gin"
	"google.golang.org/grpc"

	"gitee.com/csingo/cContext"
	"gitee.com/csingo/cLog"
)

func GRPCRequest[C any](ctx *gin.Context, client RpcClientInterface, f func(cc grpc.ClientConnInterface) C, method string, req any) (rsp any, err error) {
	pkg, app, service := client.RpcClientName()
	conn := client_container.GetGRPCConnection(pkg, app, service)

	svc := f(conn)
	svcMethod := reflect.ValueOf(svc).MethodByName(method)
	if !svcMethod.IsValid() || svcMethod.IsNil() {
		err = fmt.Errorf("grpc client method not found")
		cLog.WithContext(ctx, map[string]any{
			"source":  "cRpc.GRPCRequest",
			"pkg":     pkg,
			"app":     app,
			"service": service,
			"method":  method,
		}).Error("grpc 请求方法调用失败")
		return
	}

	newCtx := cContext.GinToGrpc(ctx)
	params := []reflect.Value{
		reflect.ValueOf(newCtx),
		reflect.ValueOf(req),
	}

	result := svcMethod.Call(params)
	if len(result) != 2 {
		err = fmt.Errorf("grpc request returns invalid result")
		cLog.WithContext(ctx, map[string]any{
			"source":  "cRpc.GRPCRequest",
			"pkg":     pkg,
			"app":     app,
			"service": service,
			"method":  method,
		}).Error("grpc 请求结果异常")
		return
	}

	rsp = result[0].Interface()
	errors.As(err, result[1].Interface())

	return
}
